package codeGenerator.visitor;

import java.util.Iterator;

import model.AttributeElement;
import model.ClasseElement;
import model.CompositeElement;
import codeGenerator.JavaFileWriter;

public class MemberPrintingVisitor implements IMetaModelVisitor {

	protected JavaFileWriter mWriter;

	@Override
	public void visitClasseElement(ClasseElement aClasseElement) {

		this.addListImports(aClasseElement);

		this.mWriter.print(aClasseElement.getVisibility() + " ");

		if (aClasseElement.isAbstract()) {
			this.mWriter.print("abstract ");
		}

		this.mWriter.print("class ");

		this.mWriter.print(aClasseElement.getName() + " ");

		// Si un heritage est present
		if (!aClasseElement.getExtends().isEmpty()) {
			this.mWriter.print("extends ");
			this.mWriter.print(aClasseElement.getExtends() + " ");
		}

		this.mWriter.println(" {");

		// Ajout attributs composite
		Iterator<CompositeElement> compositeIt = aClasseElement.getComposites()
				.iterator();
		while (compositeIt.hasNext()) {
			compositeIt.next().accept(this);
		}

		// Ajout attributs
		Iterator<AttributeElement> attributeIt = aClasseElement.getAttributes()
				.iterator();
		while (attributeIt.hasNext()) {
			attributeIt.next().accept(this);
		}

	}

	protected void addListImports(ClasseElement aClasseElement) {

		boolean shouldImportList = false;

		// Ajout attributs composite
		Iterator<CompositeElement> compositeIt = aClasseElement.getComposites()
				.iterator();
		while (compositeIt.hasNext()) {
			if (compositeIt.next().isMultiple()) {
				shouldImportList = true;
				break;
			}
		}

		// Si des attributs multiples sont présent
		if (shouldImportList) {
			this.mWriter.println("import java.util.ArrayList;");
			this.mWriter.println("import java.util.List;");
			this.mWriter.printNewLine();
		}
	}

	@Override
	public void visitAttributeElement(AttributeElement anAttributeElement) {

		this.mWriter.tab(1);
		this.mWriter.print(anAttributeElement.getVisibility() + " ");
		this.mWriter.print(anAttributeElement.getType() + " ");
		this.mWriter.print(anAttributeElement.getName() + " = ");

		// si une valeur par défaut a été définie
		if (anAttributeElement.getDefaultValue() != null) {
			this.mWriter.print(anAttributeElement.getDefaultValue());
		} else {
			this.mWriter.print("null");
		}

		this.mWriter.println(";");
	}

	@Override
	public void visitCompositeElement(CompositeElement aCompositeElement) {

		this.mWriter.tab(1);
		this.mWriter.print(aCompositeElement.getVisibility() + " ");

		// Ecriture du type de l'attribut composite
		// Si c'est un attribut non multiple
		if (!aCompositeElement.isMultiple()) {
			this.mWriter.print(aCompositeElement.getType() + " ");
		}
		// sinon
		else {
			this.mWriter.print("List<" + aCompositeElement.getCompleteType()
					+ "> ");
		}

		// Ecriture du nom de l'attribut
		this.mWriter.print(aCompositeElement.getName() + " = ");

		// Ecriture de la valeur de l'attribut composite
		// Si c'est un attribut non multiple
		if (!aCompositeElement.isMultiple()) {
			this.mWriter.print("null");
		}
		// sinon
		else {
			this.mWriter.print("new ArrayList<"
					+ aCompositeElement.getCompleteType() + ">()");
		}

		this.mWriter.println(";");
	}

	public void setWriter(JavaFileWriter mWriter) {
		this.mWriter = mWriter;
	}

}
